package edu.xust.core;

import edu.xust.config.Controller;
import edu.xust.config.Repository;
import edu.xust.config.RequestMapping;
import edu.xust.config.Service;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * initMapping 有两个 集合 别用于保存 controller 自定义url名字对应关系
 * 和method 自定义url名字对应关系
 */
public class InitMapping {
    public static Map<String, Class> controllerMaps = new HashMap<String, Class>();
    public static Map<String, Method> methodMaps = new HashMap<String, Method>();
    public static Map<String, Object> serviceMaps = new HashMap<String, Object>();
    public static Map<String, Object> daoMaps = new HashMap<String, Object>();
    public static Map<String, Object> mapperMaps = new HashMap<String, Object>();
    public static SqlSession sqlSession;

    /**
     * 如果传入了controller包的完整地址 就将真实路径下的class文件全部扫描出来
     *
     * @param controllerRealPath
     */
    public static void initController(String controllerRealPath) throws ClassNotFoundException {
        File file = new File(controllerRealPath);
        String[] controllerFileNames = file.list();
        String packageName = "edu.xust.web.controller.";//controller包完整包名
        for (String controllerFileName : controllerFileNames) {
            String fullClassName = packageName + controllerFileName.replace(".class", "");//通过报名+类名得到完整的类名
            Class clazz = Class.forName(fullClassName);//通过反射得到类对象
            if (clazz.isAnnotationPresent(Controller.class)) {
                Controller controller = (Controller) clazz.getAnnotation(Controller.class);
                String url = controller.value();
                InitMapping.controllerMaps.put(url, clazz);//循环结束所有的controller类对象都和url进行了绑定
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(RequestMapping.class)) {//对controller类的每一个方法都循环是否有RequestMapping注解 如果有 得到注解的值
                        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                        String methodUrl = requestMapping.value();
                        InitMapping.methodMaps.put(methodUrl, method);//将method请求路径methodUrl和method类对象绑定

                    }
                }
            }
        }

    }

    public static void initService(String serviceRealPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        File file = new File(serviceRealPath);
        String[] serviceFileNames = file.list();
        String packageName = "edu.xust.service.impl.";//controller包完整包名
        for (String serviceFileName : serviceFileNames) {
            String fullClassName = packageName + serviceFileName.replace(".class", "");//通过报名+类名得到完整的类名
            Class clazz = Class.forName(fullClassName);//通过反射得到类对象

           Object serviceObj = clazz.newInstance();
           if(clazz.isAnnotationPresent(Service.class)) {
               Service service = (Service) clazz.getAnnotation(Service.class);
               serviceMaps.put(service.value(), serviceObj);//将各个serviceImpl类对象上service注解中的值作为key和serviceObj对象成对存放
           }
        }
    }

    public static void initDao(String daoRealPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        File file = new File(daoRealPath);
        String[] daoFileNames = file.list();
        String packageName = "edu.xust.dao.impl.";//dao包完整包名
        for (String daoFileName : daoFileNames) {
            String fullClassName = packageName + daoFileName.replace(".class", "");//通过报名+类名得到完整的类名
            Class clazz = Class.forName(fullClassName);//通过反射得到类对象
            Object daoObj = clazz.newInstance();
            if(clazz.isAnnotationPresent(Repository.class)) {
                Repository repository = (Repository) clazz.getAnnotation(Repository.class);
                daoMaps.put(repository.value(), daoObj);//将各个serviceImpl类对象上service注解中的值作为key和serviceObj对象成对存放
            }
        }
    }

    public static void initMapper(String mapperRealPath, SqlSession sqlSession) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        File file = new File(mapperRealPath);
        String[] mapperFileNames = file.list();
        String packageName = "edu.xust.mapper.";//controller包完整包名
        for (String mapperFileName : mapperFileNames) {
            if (mapperFileName.indexOf(".xml")<0) {
                String fullClassName = packageName + mapperFileName.replace(".class", "");//通过报名+类名得到完整的类名
                Class mapperClazz = Class.forName(fullClassName);//通过反射得到类对象

                Object mapperObj = sqlSession.getMapper(mapperClazz);
                String mapperClsName = mapperClazz.getSimpleName();
                String firstChar = mapperClsName.substring(0,1);
                String lowerFirstChar = firstChar.toLowerCase();
                mapperMaps.put(lowerFirstChar+mapperClsName.substring(1), mapperObj);//将各个serviceImpl类对象上service注解中的值作为key和serviceObj对象成对存放
            }
        }
        }
    public static void initDataSourceAndMapperMap(String mapperRealPath) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
        Reader reader = Resources.getResourceAsReader("config.xml");//读取根目录下的confi.xml
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        sqlSession = sqlSessionFactory.openSession();//通过连接会话工厂得到一个连接
        InitMapping.initMapper(mapperRealPath,sqlSession);
        reader.close();
    }

}